package sudokus;

import io.SudokuReader;

import java.util.ArrayList;

import sudokus.constraints.BasicColumnConstraint;
import sudokus.constraints.BasicRowConstraint;
import sudokus.constraints.Constraint;

import datamodel.Field;
import datamodel.Grid;

/**
 * Abstract super class that contains all methods and attributes, every Sudoku
 * needs
 * 
 * @author Lukas
 * 
 */
public abstract class Sudoku {

	/** Grid of the Sudoku */
	private Grid g;
	/**
	 * Contains all basic row and column constraints defined by the class Sudoku
	 */
	private ArrayList<Constraint> constraintList;

	/**
	 * Loads the Sudoku from the .xml file defined by the path
	 * 
	 * @param path
	 *            Absolute path of the .xml file containing the Sudoku
	 * @throws NullPointerException
	 *             if path = null
	 */
	public Sudoku(String path) {
		if (path != null) {
			this.g = SudokuReader.read(path);
		} else
			throw new NullPointerException("Path of Sudoku is null!");
		constraintList = new ArrayList<Constraint>();
		registerBasicRowConstraints();
		registerBasicColumnConstraints();
		g.init();
	}

	/**
	 * Registers for each column a {@link BasicColumnConstraint}
	 */
	private void registerBasicColumnConstraints() {
		Field f;
		ArrayList<Field> fieldList;
		for (int x = 0; x < g.getXMax(); x++) {
			fieldList = new ArrayList<Field>();
			for (int y = 0; y < g.getYMax(); y++) {
				f = getField(x, y);
				fieldList.add(f);
			}
			constraintList.add(new BasicColumnConstraint(fieldList));
		}
	}//endmethod

	/**
	 * Registers for each row a {@link BasicRowConstraint}.
	 */
	private void registerBasicRowConstraints() {
		Field f;
		ArrayList<Field> fieldList;
		for (int y = 0; y < g.getYMax(); y++) {
			fieldList = new ArrayList<Field>();
			for (int x = 0; x < g.getXMax(); x++) {
				f = getField(x, y);
				fieldList.add(f);
			}
			constraintList.add(new BasicRowConstraint(fieldList));
		}
	}

	public void check() {
		Constraint c;
		for (int i = 0; i<constraintList.size();) {
			c = constraintList.get(i);
			if (!c.isFinished()) {
				c.apply();
				i++;
			} else {
				constraintList.remove(c);
			}
		}
	}

	public int getWidth() {
		return g.getXMax();
	}

	public int getHeigth() {
		return g.getYMax();
	}

	public Field getField(int x, int y) {
		return g.getField(x, y);
	}

	@Override
	public String toString() {
		return g.toString();
	}
}
